<html>
<head><meta charset="utf-8"><title>stacked borrows: Overlapping &amp;RefCell&lt;T&gt; and &amp;mut T · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html">stacked borrows: Overlapping &amp;RefCell&lt;T&gt; and &amp;mut T</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="147361970"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147361970" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147361970">(Nov 09 2018 at 10:05)</a>:</h4>
<p><span class="user-mention" data-user-id="116009">@nikomatsakis</span> I did some more refactoring after we talked yesterday, and now I have something that I am pretty happy with. It might be even nicer if we had type information on actual memory accesses, but alas, this is good enough I think. The key idea was to accept that we have two different "stack traversals":</p>
<ul>
<li>One done on a deref (evaluating the <code>*</code> operator), typed, which checks whether the <code>Uniq</code> tag is present and whether things are sufficiently frozen. This does not change the stack, but if it finds a problem that means we got UB.</li>
<li>And one on actual acesses, untyped (just knows whether this is read or write), which pops until it finds a matching item. This cannot check freezing, and when reading it will happily match a <code>Uniq</code> pointer with a <code>Shr</code> item because more reads are always okay. So this is more liberal than the deref check, but it <em>does</em> pop the stack until it finds something, invalidating pointers that may no longer be used. (We do <em>not</em> match <code>Uniq</code> ptrs with <code>Shr</code> items when writing, so that we can be sure after a write through a mutable reference that this is now again the exclusive ref to be used for this location.)</li>
</ul>
<p>This means we have three core per-location borrow operations: deref, access, create.<br>
A reborrow is then <em>generally</em> described as doing all of those operations (deref original ptr, then access with it [write access if we are creating a mutable borrow], then create new borrow), <em>except</em> that if we create a raw borrow, we <a href="https://github.com/RalfJung/miri/blob/escape-to-raw/src/stacked_borrows.rs#L336-L355" target="_blank" title="https://github.com/RalfJung/miri/blob/escape-to-raw/src/stacked_borrows.rs#L336-L355">might skip the last two steps</a>.</p>



<a name="147362075"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147362075" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147362075">(Nov 09 2018 at 10:07)</a>:</h4>
<p>I had to disable reborrowing in <code>UnsafeCell::get</code> because that one needs to immediately take a raw ptr, or else the deref done as part of the reborrow chokes: It sees a shared reference and expects it to be frozen.</p>



<a name="147592396"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147592396" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147592396">(Nov 13 2018 at 14:01)</a>:</h4>
<p><span class="user-mention" data-user-id="120791">@RalfJ</span> nice! This is not, I suppose, specific to <code>UnsafeCell::get</code>, right? That is, this is basically one of those cases where the "special semantics" of <code>&amp;x as *const u32</code> is important?</p>



<a name="147592498"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147592498" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147592498">(Nov 13 2018 at 14:03)</a>:</h4>
<p><span class="user-mention" data-user-id="116009">@nikomatsakis</span> Yes, exactly.</p>



<a name="147592549"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147592549" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147592549">(Nov 13 2018 at 14:04)</a>:</h4>
<p>Also after talking with a friend in the bus yesterday, I was able to make the special exception for raw borrows slightly less special</p>



<a name="147592574"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147592574" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147592574">(Nov 13 2018 at 14:04)</a>:</h4>
<p>It is now a general "redundant reborrow" rule: For all reborrows, we check if they are redundant, and if they are we do not do them.</p>



<a name="147592588"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147592588" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147592588">(Nov 13 2018 at 14:04)</a>:</h4>
<p>A reborrow is redundant if the new reference is <em>already</em> dereferencable, and if moreover its item in the stack lives above the item of the old reference in the stack.</p>



<a name="147593849"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147593849" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147593849">(Nov 13 2018 at 14:23)</a>:</h4>
<p>Is there a case where this applies other than raw pointers? I guess <code>&amp;T</code></p>



<a name="147593991"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147593991" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147593991">(Nov 13 2018 at 14:25)</a>:</h4>
<p>It certainly never applies for mutable references</p>



<a name="147594009"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147594009" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147594009">(Nov 13 2018 at 14:25)</a>:</h4>
<p>I am still pondering whether this changes behavior for <code>&amp;T</code> with <code>T</code> frozen</p>



<a name="147594020"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147594020" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147594020">(Nov 13 2018 at 14:25)</a>:</h4>
<p>the test suite did not see any change, that much I can say^^</p>



<a name="147594221"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147594221" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147594221">(Nov 13 2018 at 14:28)</a>:</h4>
<p>:)</p>



<a name="147600553"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147600553" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147600553">(Nov 13 2018 at 16:01)</a>:</h4>
<p>No it does not change behavior. The redundancy case can only occur if the location is already frozen, in which case both a read access and pushing a new <code>Shr</code> onto the stack do nothing.</p>



<a name="147600910"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked%20borrows%3A%20Overlapping%20%26RefCell%3CT%3E%20and%20%26mut%20T/near/147600910" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/stacked.20borrows.3A.20Overlapping.20.26RefCell.3CT.3E.20and.20.26mut.20T.html#147600910">(Nov 13 2018 at 16:06)</a>:</h4>
<p>The nice thing about this is that I can now assert that we will never push to a frozen stack, instead of having to handle that case. This will just not happen any more, it is caught by the redundancy check.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>